﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using DeepEarth.Core.Data;
using DeepEarth.Map.Core.Clustering;
namespace DeepEarth.Map.Core
{
    public abstract class UIElementLayer : BaseLayer, ILayer
    {
        //Viewmodels and elements as added to the layer
        protected readonly Dictionary<ClusterViewModel, MapItemAdorner> referenceElements;

        public IEnumerable<ClusterViewModel> ClusterViewModels
        {
            get
            {
                if (referenceElements != null && referenceElements.Any())
                    return referenceElements.Keys;
                else
                    return null;
            }
        }

        protected UIElementLayer()
        {
            layerChildren = new LayerElementCollection(base.Children);
            referenceElements = new Dictionary<ClusterViewModel, MapItemAdorner>();

            LayoutUpdated += UIElementLayer_LayoutUpdated;            
        }

        #region Properties
        // Note: This is not virtual. Canvas.Children returns UIElementCollection and UIElementLayer.Children returns LayerElementCollection
        protected LayerElementCollection layerChildren;
        public new LayerElementCollection Children
        {
            get { return layerChildren; }
        }

        public UIElementCollection BaseChildren
        {
            get { return base.Children; }
        }


        #endregion

        // used to ensure that we don't trigger synchronization too often
        int lastSynchronizationChildCount;

        // Ensure that we synchronize if a child is added
        void UIElementLayer_LayoutUpdated(object sender, System.EventArgs e)
        {
            ChildAdded();
        }

        protected virtual void ChildAdded()
        {
            if (base.Children.Count != lastSynchronizationChildCount)
            {
                lastSynchronizationChildCount = base.Children.Count;

                // This is untidy :(
                Dispatcher.BeginInvoke( () =>
                    {
                        foreach (var child in base.Children.OfType<ISelfPositioning>())
                            child.Refresh(new Point(0,0), 16848);

                        SynchronizeOnFrame();
                    }
                );
            }
        }



        public virtual void Add(GeoItemViewModel viewModel, UIElement element)
        {
            var cvm = viewModel as ClusterViewModel;

            if (cvm != null)
            {
                referenceElements.Add(cvm, (MapItemAdorner)element);
            }

            Children.Add(element);
        }

        public virtual void Remove(GeoItemViewModel viewModel, UIElement element)
        {
            Children.Remove(element);

            var removedItems = referenceElements.Keys.Where(r => r.WrappedViewModel == viewModel).ToList();

            foreach (var r in removedItems)
            {
                UIElement e = referenceElements[r];
                Children.Remove(e);
                referenceElements.Remove(r);
            }
        }

        public virtual void Clear()
        {
            referenceElements.Clear();
            Children.Clear();
        }

        #region ILayer
        public bool IsVisible
        {
            get { return Visibility == Visibility.Visible && (ParentLayer == null || ParentLayer.IsVisible); }
        }

        public ILayer ParentLayer { get; set; }
        #endregion
    }
}